#coding=utf-8

require "aio/core"

class Aio::Module::Cmd::Cisco::ShowInterfaces < Aio::Module::Cmd::Cisco
	include Aio::Module

	def initialize
		super({
			:cmd_full		=> "show interfaces",
			:cmd_short	=> "sh int",
			:author			=> "Elin",
			:description =>	"This is Cisco Command# show interfaces",
			:ranking		=> Ranking_1,
			:platform		=> "all",
			:benchmark	=> {
				:input_queue_drops	=> ["<=", 10],
				:total_output_drops	=> ["<=", 10],
				:output_queue_drops => ["<=", 10],
				:runts							=> ["<=", 10],
				:giants							=> ["<=", 10],
				:throttles					=> ["<=", 10],
				:input_errors				=> ["<=", 10],
				:crc                => ["<=", 1000],
				:frame              => ["<=", 10],
				:overrun            => ["<=", 10],
				:ignored            => ["<=", 10],
				:output_errors      => ["<=", 10],
				:collisions 				=> ["<=", 10],
				:iface_resets       => ["<=", 10],
				}
		})
	end

	Reg_Ethernet	= /Ethernet[^\.]+/
	Reg_Loopback	= /Loopback/
	Reg_SubIface	= /Ethernet.*[\.]/

	def parse
		cont = self.context.dup
		useful[:interface] = {}
		cont.readline_range_loop(/, line protocol/, /, line protocol/,
					 {:before => true}) do |cont_layer|
			case device_template
			when Template_3	# 当是ASA的时候
				parse_asa(cont_layer)
			else
				switch_iface(cont_layer)
			end
		end
	end

	def switch_iface(context)
		case context[0]
		when Reg_Ethernet
			parse_eth(context)
		when Reg_Loopback
			parse_eth(context)
		when Reg_SubIface
			parse_subiface(context)
		end
	end

	def parse_asa(context)
		iface = {}
		iface_id = nil

		context.readline_match_block(/Interface (?<iface_id>.*) "(?<side>.*)", is (?<state>.*), line protocol is (?<proto_state>.*)/) do |block|
			iface_id = block[:iface_id].strip
			useful[:interface][iface_id] = iface
			block.update(iface, :iface_id)
			block.update(iface, :side)
			block.update(iface, :state)
			block.update(iface, :proto_state)
		end

		return if iface.empty?
		context.readline_match_block(/MAC address (?<mac>[^,]*)/) do |block|
			block.update(iface, :mac)
		end
		context.readline_match_block(/IP address (?<addr>.*), subnet mask (?<mask>.*)/) do |block|
			block.update(iface, :addr)
			block.update(iface, :mask, Aio::Base::Toolkit::IPAddr.mask_dotted_to_i(block[:mask]).to_s)
		end
		iface_stat(context, iface)
	end

	def parse_eth(context)
		iface = {}
		iface_id = nil

		context.readline_match_block(/(?<iface_id>.*) is (?<state>.*), line protocol is (?<proto_state>.*)/) do |block|
			iface_id = block[:iface_id].strip
			useful[:interface][iface_id] = iface
			block.update(iface, :iface_id)
			block.update(iface, :state)
			block.update(iface, :proto_state)
		end
			
		context.readline_match_block(/Hardware .* address is (?<mac>[^\s]*) /) do |block|
			block.update(iface, :mac)
		end
		context.readline_match_block(/Description: (?<description>.*)/) do |block|
			block.update(iface, :description)
		end
		context.readline_match_block(/Internet address is (?<addr>[^\/]+)\/(?<mask>\d+)/) do |block|
			block.update(iface, :addr)
			block.update(iface, :mask)
		end
		context.readline_match_block(/Encapsulation (?<encapsulation>[^\s]*)/) do |block|
			block.update(iface, :encapsulation)
		end
		context.readline_match_block(/(?<duplex>.*[Dd]uplex), (?<speed>.*), /) do |block|
			block.update(iface, :duplex)
			block.update(iface, :speed)
		end
		iface_stat(context, iface)
	end

	# 接口的计数
	def iface_stat(context, iface)
		#只有当:state 为UP的才会进行下面的操作
		if iface[:state] =~ /up/
			context.readline_match_block(/Input queue: \d+\/\d+\/(?<input_queue_drops>\d+)\/\d+ \(size\/max\/drops\/flushes\); Total output drops: (?<total_output_drops>\d+)/) do |block|
				block.warning_ordinary(iface, :input_queue_drops, self)
				block.warning_ordinary(iface, :total_output_drops, self)
			end
			context.readline_match_block(/Output queue: \d+\/\d+\/(?<output_queue_drops>\d+) \(size\/max total\/drops\)/) do |block|
				block.warning_ordinary(iface, :output_queue_drops, self)
			end
			context.readline_match_block(/(?<runts>\d+) runts, (?<giants>\d+) giants, (?<throttles>\d+) throttles/) do |block|
				block.warning_ordinary(iface, :runts, self)
				block.warning_ordinary(iface, :giants, self)
				block.warning_ordinary(iface, :throttles, self)
			end
			context.readline_match_block(/(?<input_errors>\d+) input errors, (?<crc>\d+) CRC, (?<frame>\d+) frame, (?<overrun>\d+) overrun, (?<ignored>\d+) ignored/) do |block|
				block.warning_serious(iface, :input_errors, self)
				block.warning_serious(iface, :crc, self)
				block.warning_ordinary(iface, :frame, self)
				block.warning_ordinary(iface, :overrun, self)
				block.warning_ordinary(iface, :ignored, self)
			end
			context.readline_match_block(/(?<output_errors>\d+) output errors, (?<collisions>\d+) collisions, (?<iface_resets>\d+) interface resets/) do |block|
				block.warning_serious(iface, :output_errors, self)
				block.warning_ordinary(iface, :collisions, self)
				block.warning_ordinary(iface, :iface_resets, self)
			end
		end
	end

	def parse_subiface(context)
		iface = {}
		iface_id = nil
		context.readline_match_block(/(?<iface_id>.*) is (?<state>.*), line protocol is (?<proto_state>.*)/) do |block|
			iface_id = block[:iface_id]
			useful[:interface][iface_id] = iface
			update(iface, :iface_id)
			update(iface, :state)
			update(iface, :proto_state)
		end
		context.readline_match_block(/Hardware .* address is (?<mac>.*) /)  do |block|
			update(iface, :mac)
		end
		context.readline_match_block(/Description: (?<description>.*)/) do |block|
			update(iface, :description)
		end
		context.readline_match_block(/Internet address is (?<addr>.*)/) do |block|
			update(iface, :addr)
		end
		context.readline_match_block(/Encapsulation (?<encapsulation>.*) Virtual LAN, Vlan ID (?<vlan_id>.*)/) do |block|
			update(iface, :encapsulation)
			update(iface, :vlan_id)
		end
	end

end

